using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Reflection;
using System.Windows.Forms;
using System.Drawing;
using System.IO;
namespace RefCheckRewrite
{
  public class RefCheck
  {
    private FileInfo _assemblyFile;
    private Dictionary<string,string> CheckedAssemblies=new Dictionary<string,string>();
    private ArrayList FailedAssemblies=new ArrayList();
    public System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender,ResolveEventArgs args)
    {
      string asmName=_assemblyFile.Directory.FullName+"\\"+args.Name.Substring(0,args.Name.IndexOf(","))+".dll";
      return Assembly.LoadFile(asmName);
    }
    public RefCheck(FileInfo fileInfo)
    {
      this._assemblyFile=fileInfo;
    }
    public void Validate(TreeView tree)
    {
      tree.Nodes.Clear();
      Assembly assembly=null;
      AppDomain.CurrentDomain.AssemblyResolve-=CurrentDomain_AssemblyResolve;
      AppDomain.CurrentDomain.AssemblyResolve+=CurrentDomain_AssemblyResolve;
      try
      {
        //AppDomain domain=AppDomain.CreateDomain("test");
        //assembly=domain.Load(new AssemblyName(this._assemblyFile.FullName));

        assembly=Assembly.LoadFile(this._assemblyFile.FullName);
        //Assembly[] arr=AppDomain.CurrentDomain.GetAssemblies();
        //Console.WriteLine(arr.Length);

      }
      catch(Exception)
      {
        tree.Nodes.Add(this._assemblyFile.FullName+" - load FAILED");
      }
      if(null!=assembly)
      {
        TreeNode node=new TreeNode(assembly.ToString());
        node.ToolTipText=assembly.Location;
        tree.Nodes.Add(node);
        AssemblyName[] referencedAssemblies=assembly.GetReferencedAssemblies();
        foreach(AssemblyName name in referencedAssemblies)
        {
          this.ValidateAssembly(name,tree.Nodes[tree.Nodes.Count-1]);
        }
        if(this.FailedAssemblies.Count>0)
        {
          tree.Nodes.Add(string.Format("{0} assemblies failed to load:",this.FailedAssemblies.Count));
          for(int i=0;i<this.FailedAssemblies.Count;i++)
          {
            tree.Nodes[tree.Nodes.Count-1].Nodes.Add((FailedAssemblies[i] as TreeNode).Clone() as TreeNode);
          }
          tree.Nodes[tree.Nodes.Count-1].Expand();
        }
        else
        {
          tree.Nodes.Add(string.Format("All assemblies loaded OK!"));
        }
        tree.Nodes[0].Expand();
      }
    }
    private void ValidateAssembly(AssemblyName assemblyName,TreeNode treeNode)
    {
      string key=assemblyName.ToString();
      try
      {
        if(!this.CheckedAssemblies.ContainsKey(key))
        {
          CheckedAssemblies.Add(key,"");
          Assembly assembly=Assembly.Load(assemblyName);
          TreeNode nod=new TreeNode(string.Format("{0} ({1}) - OK",assemblyName.Name,assemblyName.Version));
          nod.ToolTipText=assembly.Location;
          CheckedAssemblies[key]=assembly.Location;
          if(assembly.GlobalAssemblyCache)
            nod.ForeColor=Color.Blue;
          bool refonly=assembly.ReflectionOnly;
          treeNode.Nodes.Add(nod);
          AssemblyName[] referencedAssemblies=assembly.GetReferencedAssemblies();
          foreach(AssemblyName name in referencedAssemblies)
          {
            this.ValidateAssembly(name,treeNode.Nodes[treeNode.Nodes.Count-1]);
          }
        }
        else
        {
          TreeNode nod=new TreeNode(string.Format("{0} ({1}) - CHECKED",assemblyName.Name,assemblyName.Version));
          nod.ForeColor=CheckedAssemblies[key]!=""?Color.Green:Color.Brown;
          treeNode.Nodes.Add(nod);
        }
      }
      catch(Exception exception)
      {
        TreeNode red=new TreeNode(string.Format("{0} ({1}) - FAILED",assemblyName.ToString(),assemblyName.Version));
        red.ForeColor=Color.Red;
        red.ToolTipText=exception.Message;
        treeNode.Nodes.Add(red);
        this.FailedAssemblies.Add(red);
      }
    }
  }
}
